package gui;

import gui.client.ClientTab;
import gui.dialogs.Alert;
import gui.payment.PaymentTab;
import gui.workshop.WorkshopTab;

import java.sql.SQLException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;

import databasetranslation.ClientList;
import databasetranslation.DatabaseLists;
import databasetranslation.PaymentList;
import databasetranslation.SubscriptionList;
import databasetranslation.WorkshopList;

public class App {
	
	private DatabaseLists databaseLists;
	private static final int refreshInterval = 2000; 
	
	private ClientTab clientsTab;
	private WorkshopTab workshopsTab;
	private PaymentTab paymentsTab;
	
	private Display display;
	private Shell shell;
	
	private Runnable timer;
	
	/**
	 * Create a new App. It opens the main window of the application.
	 * 
	 * @param databaseLists the lists with data from the database
	 * @param databaseRefresh whether to refresh the data in the application regularly 
	 */
	public App(DatabaseLists databaseLists, boolean databaseRefresh) {
		this.databaseLists = databaseLists;
		build();
		if(databaseRefresh) autorefresh();
		mainloop();
	}

	/**
	 * Create the main window, with the tabs.
	 */
	private void build() {    
		display = new Display();
		shell = new Shell(display);   
		
		shell.setText("Centrum voor creative ontwikkeling");
        shell.setSize(1400, 700);
        shell.setLayout(new GridLayout(1, false));

		final TabFolder tabFolder = new TabFolder(shell, SWT.NONE);
		tabFolder.setLayoutData(getExpandGridData());
		tabFolder.setLayout(new GridLayout(1, false));
		
		clientsTab = new ClientTab(this, tabFolder, getClientList());
		workshopsTab = new WorkshopTab(this, tabFolder, getWorkshopList());
		paymentsTab = new PaymentTab(this, tabFolder, getPaymentList());
	}
	
	/**
	 * Automatically refresh the data with the data in the database
	 */
	public void autorefresh() {
	    timer = new Runnable() {
	        public void run() {
	        	try {
	        		// only update the GUI when something has changed, to avoid flickering
	        		if ( ! databaseLists.isEqualToDatabase()) {
	        			databaseLists.importDataFromDatabase();
	        			updateAll();
	        		}
				} catch (SQLException e) {
					dbCommunicationException(e);
				}       	
	        	display.timerExec(refreshInterval, this);
	        }
	    };
	    display.timerExec(refreshInterval, timer);
	}
	
	/**
	 * Enter the main event loop.
	 */
	private void mainloop() {
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) display.sleep ();
		}
		display.dispose ();
	}
	
	/**
	 * Return a new GridData instance that tends to expand as much as possible.
	 * @return new GridData instance
	 */
	private static GridData getExpandGridData() {
		GridData expandCell = new GridData();
		expandCell.horizontalAlignment = GridData.FILL;
		expandCell.grabExcessHorizontalSpace = true;
		expandCell.verticalAlignment = GridData.FILL;
		expandCell.grabExcessVerticalSpace = true;
		return expandCell;
	}
	
	/**
	 * Update the gui so that the gui corresponds to the data in the databaselists. 
	 */
	public void updateAll() {
		clientsTab.update();
		workshopsTab.update();
		paymentsTab.update();
	}

	/**
	 * Alert the user that there was a database communication problem
	 */
	public void dbCommunicationException(SQLException e) {
		System.out.println("DB communication problem:" + e.getMessage());
		new Alert(shell, 
				"Database probleem", 
				"Er is een probleem opgetreden tijdens het communicaren met de database. " +
					"De gegevens zijn mogelijk niet opgeslagen."
		).open();
	}
	
	public ClientList getClientList() {
		return databaseLists.getClientList();
	}
	
	public WorkshopList getWorkshopList() {
		return databaseLists.getWorkshopList();
	}
	
	public PaymentList getPaymentList() {
		return databaseLists.getPaymentList();
	}
	
	public SubscriptionList getSubscriptionList() {
		return databaseLists.getSubscriptionList();
	}

	public Shell getShell() {
		return shell;
	}
} 

